home *** CD-ROM | disk | FTP | other *** search
Wrap
/* * $Id: aclip.c,v 1.1.1.1 2000/04/07 19:44:51 hfrieden Exp $ * * $Date: 2000/04/07 19:44:51 $ * $Revision: 1.1.1.1 $ * * (C) 1999 by Hyperion * All rights reserved * * This file is part of the MiniGL library project * See the file Licence.txt for more details * */ static char rcsid[] = "$Id: aclip.c,v 1.1.1.1 2000/04/07 19:44:51 hfrieden Exp $"; #include "sysinc.h" #include "vertexarray.h" #include <math.h> #define LERP(t,a,b) \ ( (a) + (float)t * ( (b) - (a) ) ) #define CLIP_EPS (1e-7) #define x1 (a->bx) #define y1 (a->by) #define z1 (a->bz) #define w1 (a->bw) #define x2 (b->bx) #define y2 (b->by) #define z2 (b->bz) #define w2 (b->bw) static void A_ClipWZero(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading) { float w; ULONG outcode; float t = (CLIP_EPS-w1)/(w2-w1); if(shading == GL_SMOOTH) { r->v.color.a = LERP(t,a->v.color.a, b->v.color.a); r->v.color.r = LERP(t,a->v.color.r, b->v.color.r); r->v.color.g = LERP(t,a->v.color.g, b->v.color.g); r->v.color.b = LERP(t,a->v.color.b, b->v.color.b); } r->v.u = LERP(t,a->v.u, b->v.u); r->v.v = LERP(t,a->v.v, b->v.v); r->bx = LERP(t,a->bx, b->bx); r->by = LERP(t,a->by, b->by); r->bz = LERP(t,a->bz, b->bz); r->bw = CLIP_EPS; w = r->bw; outcode = 0; if (-w > r->bx) { outcode |= MGL_CLIP_LEFT; } else if (r->bx > w) { outcode |= MGL_CLIP_RIGHT; } if (-w > r->by) { outcode |= MGL_CLIP_BOTTOM; } else if (r->by > w) { outcode |= MGL_CLIP_TOP; } if (-w > r->bz) { outcode |= MGL_CLIP_BACK; } else if (r->bz > w) { outcode |= MGL_CLIP_FRONT; } r->outcode = outcode; } static void A_ClipTop(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading) { float w; ULONG outcode; float t = (w1-y1)/((w1-y1)-(w2-y2)); if(shading == GL_SMOOTH) { r->v.color.a = LERP(t,a->v.color.a, b->v.color.a); r->v.color.r = LERP(t,a->v.color.r, b->v.color.r); r->v.color.g = LERP(t,a->v.color.g, b->v.color.g); r->v.color.b = LERP(t,a->v.color.b, b->v.color.b); } r->v.u = LERP(t,a->v.u, b->v.u); r->v.v = LERP(t,a->v.v, b->v.v); r->bx = LERP(t,a->bx, b->bx); r->bz = LERP(t,a->bz, b->bz); r->bw = LERP(t,a->bw, b->bw); r->by = r->bw; /* Surgeon: this is always the 2nd last routine called, so here is no need to recode since a top-code means that there can be no bottom-code - we can safely set the outcode of the clipped vert to 0 */ #if 1 r->outcode = 0; #else w = r->bw; outcode = 0; if (r->bw < CLIP_EPS ) { outcode |= MGL_CLIP_NEGW; } if (-w > r->bx) { outcode |= MGL_CLIP_LEFT; } else if (r->bx > w) { outcode |= MGL_CLIP_RIGHT; } if (-w > r->bz) { outcode |= MGL_CLIP_BACK; } else if (r->bz > w) { outcode |= MGL_CLIP_FRONT; } r->outcode = outcode; #endif } static void A_ClipBottom(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading) { float w; ULONG outcode; float t = (w1+y1)/((w1+y1)-(w2+y2)); if(shading == GL_SMOOTH) { r->v.color.a = LERP(t,a->v.color.a, b->v.color.a); r->v.color.r = LERP(t,a->v.color.r, b->v.color.r); r->v.color.g = LERP(t,a->v.color.g, b->v.color.g); r->v.color.b = LERP(t,a->v.color.b, b->v.color.b); } r->v.u = LERP(t,a->v.u, b->v.u); r->v.v = LERP(t,a->v.v, b->v.v); r->bx = LERP(t,a->bx, b->bx); r->bz = LERP(t,a->bz, b->bz); r->bw = LERP(t,a->bw, b->bw); r->by = -r->bw; /* Surgeon: this is always the last routine called, so here is no need to recode - we can safely set the outcode of the clipped vert to 0 */ #if 1 r->outcode = 0; #else w = r->bw; outcode = 0; if (r->bw < CLIP_EPS ) { outcode |= MGL_CLIP_NEGW; } if (-w > r->bx) { outcode |= MGL_CLIP_LEFT; } else if (r->bx > w) { outcode |= MGL_CLIP_RIGHT; } if (-w > r->bz) { outcode |= MGL_CLIP_BACK; } else if (r->bz > w) { outcode |= MGL_CLIP_FRONT; } r->outcode = outcode; #endif } static void A_ClipLeft(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading) { float w; ULONG outcode; float t = (w1+x1)/((w1+x1)-(w2+x2)); if(shading == GL_SMOOTH) { r->v.color.a = LERP(t,a->v.color.a, b->v.color.a); r->v.color.r = LERP(t,a->v.color.r, b->v.color.r); r->v.color.g = LERP(t,a->v.color.g, b->v.color.g); r->v.color.b = LERP(t,a->v.color.b, b->v.color.b); } r->v.u = LERP(t,a->v.u, b->v.u); r->v.v = LERP(t,a->v.v, b->v.v); r->by = LERP(t,a->by, b->by); r->bz = LERP(t,a->bz, b->bz); r->bw = LERP(t,a->bw, b->bw); r->bx = -r->bw; w = r->bw; outcode = 0; /* if (r->bw < CLIP_EPS ) { outcode |= MGL_CLIP_NEGW; } */ if (-w > r->by) { outcode |= MGL_CLIP_BOTTOM; } else if (r->by > w) { outcode |= MGL_CLIP_TOP; } if (-w > r->bz) { outcode |= MGL_CLIP_BACK; } else if (r->bz > w) { outcode |= MGL_CLIP_FRONT; } r->outcode = outcode; } static void A_ClipRight(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading) { float w; ULONG outcode; float t = (w1-x1)/((w1-x1)-(w2-x2)); if(shading == GL_SMOOTH) { r->v.color.a = LERP(t,a->v.color.a, b->v.color.a); r->v.color.r = LERP(t,a->v.color.r, b->v.color.r); r->v.color.g = LERP(t,a->v.color.g, b->v.color.g); r->v.color.b = LERP(t,a->v.color.b, b->v.color.b); } r->v.u = LERP(t,a->v.u, b->v.u); r->v.v = LERP(t,a->v.v, b->v.v); r->by = LERP(t,a->by, b->by); r->bz = LERP(t,a->bz, b->bz); r->bw = LERP(t,a->bw, b->bw); r->bx = r->bw; w = r->bw; outcode = 0; /* if (r->bw < CLIP_EPS ) { outcode |= MGL_CLIP_NEGW; } */ if (-w > r->by) { outcode |= MGL_CLIP_BOTTOM; } else if (r->by > w) { outcode |= MGL_CLIP_TOP; } if (-w > r->bz) { outcode |= MGL_CLIP_BACK; } else if (r->bz > w) { outcode |= MGL_CLIP_FRONT; } r->outcode = outcode; } static void A_ClipFront(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading) { float w; ULONG outcode; float t = (w1-z1)/((w1-z1)-(w2-z2)); if(shading == GL_SMOOTH) { r->v.color.a = LERP(t,a->v.color.a, b->v.color.a); r->v.color.r = LERP(t,a->v.color.r, b->v.color.r); r->v.color.g = LERP(t,a->v.color.g, b->v.color.g); r->v.color.b = LERP(t,a->v.color.b, b->v.color.b); } r->v.u = LERP(t,a->v.u, b->v.u); r->v.v = LERP(t,a->v.v, b->v.v); r->bx = LERP(t,a->bx, b->bx); r->by = LERP(t,a->by, b->by); r->bw = LERP(t,a->bw, b->bw); r->bz = r->bw; w = r->bw; outcode = 0; /* if (r->bw < CLIP_EPS ) { outcode |= MGL_CLIP_NEGW; } if (-w > r->bx) { outcode |= MGL_CLIP_LEFT; } else if (r->bx > w) { outcode |= MGL_CLIP_RIGHT; } */ if (-w > r->by) { outcode |= MGL_CLIP_BOTTOM; } else if (r->by > w) { outcode |= MGL_CLIP_TOP; } r->outcode = outcode; } static void A_ClipBack(MGLVertex *a, MGLVertex *b, MGLVertex *r, GLenum shading) { float w; ULONG outcode; float t = (w1+z1)/((w1+z1)-(w2+z2)); if(shading == GL_SMOOTH) { r->v.color.a = LERP(t,a->v.color.a, b->v.color.a); r->v.color.r = LERP(t,a->v.color.r, b->v.color.r); r->v.color.g = LERP(t,a->v.color.g, b->v.color.g); r->v.color.b = LERP(t,a->v.color.b, b->v.color.b); } r->v.u = LERP(t,a->v.u, b->v.u); r->v.v = LERP(t,a->v.v, b->v.v); r->bx = LERP(t,a->bx, b->bx); r->by = LERP(t,a->by, b->by); r->bw = LERP(t,a->bw, b->bw); r->bz = -r->bw; w = r->bw; outcode = 0; /* if (r->bw < CLIP_EPS ) { outcode |= MGL_CLIP_NEGW; } if (-w > r->bx) { outcode |= MGL_CLIP_LEFT; } else if (r->bx > w) { outcode |= MGL_CLIP_RIGHT; } */ if (-w > r->by) { outcode |= MGL_CLIP_BOTTOM; } else if (r->by > w) { outcode |= MGL_CLIP_TOP; } r->outcode = outcode; } #undef x1 #undef y1 #undef z1 #undef w1 #undef x2 #undef y2 #undef z2 #undef w2 /* ** Complicated clipping macro stuff. */ #define VERTP(i) &(context->VertexBuffer[a->verts[i]]) #define VERT(i) (context->VertexBuffer[a->verts[i]]) #define POLYSWAP \ if (b->numverts == 0){out->numverts = 0; return;} \ temp=a; a=b; b=temp; \ #define DOCLIP(edge, routine) \ if (or_codes & edge) \ { \ b->numverts = 0; \ prev = a->numverts-1; \ i=0; do { \ /* Case 1 and 4*/ \ if (!(VERT(prev).outcode & edge)) \ { \ b->verts[b->numverts] = a->verts[prev]; \ b->numverts++; \ } \ /* Case 3 and 4 */ \ if ((VERT(prev).outcode ^ VERT(i).outcode) & edge) \ { \ A_##routine (VERTP(prev), VERTP(i), &(context->VertexBuffer[free]), (const GLenum)context->ShadeModel); \ b->verts[b->numverts]=free++; \ b->numverts++; \ } \ prev = i; \ } while (++i < a->numverts); \ POLYSWAP \ } void AE_ClipPoly(GLcontext context, PolyBuffer *out, int clipstart, ULONG or_codes) { PolyBuffer output; PolyBuffer *a, *b, *temp; int i,j; int prev; int free = clipstart; a = out; b=&output; DOCLIP(MGL_CLIP_NEGW, ClipWZero); j = 0; do { or_codes |= context->VertexBuffer[a->verts[j]].outcode; j++; } while (j < a->numverts); DOCLIP(MGL_CLIP_LEFT, ClipLeft) DOCLIP(MGL_CLIP_RIGHT, ClipRight) DOCLIP(MGL_CLIP_FRONT, ClipFront) DOCLIP(MGL_CLIP_BACK, ClipBack) DOCLIP(MGL_CLIP_TOP, ClipTop) DOCLIP(MGL_CLIP_BOTTOM, ClipBottom) out->nextfree = free; out->numverts = a->numverts; j = 0; do { out->verts[j] = a->verts[j]; j++; } while (j < a->numverts); }